package org.jsola.hr.common;


import org.jsola.common.DateKit;
import org.jsola.common.DateKit8;
import org.jsola.common.DoubleKit;
import org.jsola.common.StrKit;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.sm4.SM4Utils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * @author zhr
 * @date 2018/11/27.
 * @email 日期工具类
 */
public class DateUtils {

    /**
     * date2比date1多的天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDays(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2)   //同一年
        {
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)    //闰年
                {
                    timeDistance += 366;
                } else    //不是闰年
                {
                    timeDistance += 365;
                }
            }

            return timeDistance + (day2 - day1);
        } else    //不同年
        {
            System.out.println("判断day2 - day1 : " + (day2 - day1));
            return day2 - day1;
        }
    }

    /**
     * 计算时间相差分钟数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static Integer getMinutesDiff(Date date1, Date date2) {
        Long date1Time = date1.getTime();
        Long date2Time = date2.getTime();
        Long diff = (date1Time - date2Time) / 1000 / 60;
        System.out.println("两个时间差为：" + diff.intValue() + "分钟");
        return diff.intValue();
    }

    /**
     * 时间比大小
     *
     * @param date1
     * @param date2
     * @return
     */
    public static Integer timeCompare(String date1, String date2) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        try {
            c1.setTime(formatter.parse(date1));
            c2.setTime(formatter.parse(date2));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //比当前日期小返回-1 	相等返回 0  比当前日期大 返回1
        Integer result = c1.compareTo(c2);
        return result;
    }

    /**
     * 获取指定日前的前一天
     *
     * @param strData
     * @return
     */
    public static String getPreDateByDate(String strData) {
        String preDate = "";
        Calendar c = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(strData);
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }

        c.setTime(date);
        int day1 = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day1 - 1);
        preDate = sdf.format(c.getTime());
        return preDate;
    }

    /**
     * 指定日期加上分钟数
     *
     * @param datetime
     * @param min
     * @return
     * @throws Exception
     */
    public static Date addMinutes(String datetime, int min) throws Exception {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date originalDate = formatter.parse(datetime);
        Calendar newTime = Calendar.getInstance();
        newTime.setTime(originalDate);
        newTime.add(Calendar.MINUTE, min);
        return newTime.getTime();
    }


    /**
     * 获取制定日期的后一天
     *
     * @param strData
     * @return
     */
    public static String getBeforeDateByDate(String strData) {
        String preDate = "";
        Calendar c = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(strData);
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }

        c.setTime(date);
        int day1 = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day1 + 1);
        preDate = sdf.format(c.getTime());
        return preDate;
    }

    /**
     * 获取指定日期下个月的第一天
     *
     * @param dateStr
     * @return
     */
    public static Date getFirstDayOfNextMonth(String dateStr) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = sdf.parse(dateStr);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            calendar.add(Calendar.MONTH, 1);
            return calendar.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) {
        Date date = DateKit8.parseDate("2021-01-12");
        Date date2 = DateKit8.parseDate("2021-02-12");
        List<Date> monthDifferences = getMonthDifferences(date, date2);
        System.out.println(monthDifferences.size());
    }

    /**
     * 获取明天0点时间
     *
     * @return 明天0点时间
     */
    public static Date getTomorrow() {
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DATE, 1);
            Date dateNow = calendar.getTime();
            // 明天0点
            String tomorrowS = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(dateNow);

            DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return format.parse(tomorrowS);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new Date();
    }

    /**
     * 获取司龄
     *
     * @param joinDate  入职时间
     * @param leaveDate 离职时间
     */
    public static double getJoinCompanyLength(Date joinDate, Date leaveDate) {
        if (joinDate == null) {
            return 0.0;
        }
        if (leaveDate == null) {
            // 没有离职时间,默认今天
            leaveDate = DateKit.getToday();
        }
        // 相差年数
        int yearDiff = getYearDiff(joinDate, leaveDate);

        // 获取增加年限后的新日期
        Date joinDateNew = getAddYearDate(joinDate, yearDiff);
        // 计算日期相差天数
        int diffDay = DateKit.getDaysBetween(joinDateNew, leaveDate);
        // 小数点后,相差天数/365,保留一位小数
        double diff = DoubleKit.div(diffDay, 365, 1);

        return yearDiff + diff;
    }

    /**
     * 获取增加年限后的新日期
     *
     * @param date    原日期
     * @param addYear 增加的年限
     * @return 增加年限后的新日期
     */
    private static Date getAddYearDate(Date date, int addYear) {
        int startYear = Integer.valueOf(DateKit.getYear(date));
        int endYear = startYear + addYear;
        // 根据数字年转换为字符串年
        String monthDay = getMonthAndDayStrByDate(date);
        String dateStr = endYear + monthDay;
        return DateKit.getDate("yyyyMMdd", dateStr);
    }


    /**
     * 相差年数
     *
     * @param startDate 起始时间
     * @param endDate   截止时间
     * @return 相差年数
     */
    public static int getYearDiff(Date startDate, Date endDate) {
        if (startDate == null) {
            return 0;
        }
        // 获取月份
        int startMonth = getMonthAndDayNumByDate(startDate);
        int endMonth = getMonthAndDayNumByDate(endDate);

        int startYear = Integer.valueOf(DateKit.getYear(startDate));
        int endYear = Integer.valueOf(DateKit.getYear(endDate));
        int yearDiff;
        if (endMonth >= startMonth) {
            // 截止时间的月日大于起始时间
            yearDiff = endYear - startYear;
        } else {
            // 截止时间的月日小于起始时间,少一年去补月日
            yearDiff = endYear - startYear - 1;
        }
        return yearDiff;
    }

    /**
     * 两时间相差天数、小时数、分钟数、秒数、字符串
     *
     * @param endDate 截止时间
     * @param nowDate 当前时间
     * @return 相差年数
     */
    public static String getDateDiffStr(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }

    /**
     * 获取月份日期
     *
     * @param date 时间
     * @return 月份日期
     */
    private static int getMonthAndDayNumByDate(Date date) {
        String month = DateKit.getFormatDate(date, "MMdd");
        if (NumberKit.isNumeric(month)) {
            return Integer.valueOf(month);
        }
        return 0;
    }

    /**
     * 获取月份日期
     *
     * @param date 时间
     * @return 月份日期
     */
    private static String getMonthAndDayStrByDate(Date date) {
        String month = DateKit.getFormatDate(date, "MMdd");
        if (NumberKit.isNumeric(month)) {
            return month;
        }
        return "0000";
    }

    /**
     * 获取月份日期
     *
     * @param date 时间
     * @return 月份日期
     */
    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取两个时间之间的月份
     *
     * @param startDate 时间
     * @param endDate   时间
     * @return 月份日期
     */
    public static List<Date> getMonthDifferences(Date startDate, Date endDate) {
        List<Date> datesInRange = new ArrayList<>();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(startDate);

        Calendar endCalendar = new GregorianCalendar();
        endCalendar.setTime(endDate);

        while (calendar.before(endCalendar) || calendar.equals(endCalendar)) {
            Date result = calendar.getTime();
            datesInRange.add(result);
            calendar.add(Calendar.MONTH, 1);
        }
        return datesInRange;

    }

    /**
     * 给一个date返回年和月
     *
     * @param date 时间
     */
    public static String[] getYearAndMonth(Date date) {
        String[] yearAndMonth = new String[2];
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        String monthAttr;
        if (month < 10) {
            monthAttr = "0" + month;
        } else {
            monthAttr = Integer.toString(month);
        }
        yearAndMonth[0] = Integer.toString(year);
        yearAndMonth[1] = monthAttr;
        return yearAndMonth;
    }

    /**
     * 返回一个Date的年
     */
    public static String getYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR) + "";
    }

    /**
     * 返回一个Date的月
     */
    public static String getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH) + 1;
        String monthAttr;
        if (month < 10) {
            monthAttr = "0" + month;
        } else {
            monthAttr = Integer.toString(month);
        }
        return monthAttr;
    }

    /**
     * 给一个date 返回形如 202001
     *
     * @param date 时间
     * @return
     */
    public static String getYearMonthStr(Date date) {
        if (ObjectUtils.isEmpty(date)) {
            return "";
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        Integer year = calendar.get(Calendar.YEAR);
        Integer month = calendar.get(Calendar.MONTH) + 1;
        String monthAttr;
        if (month < 10) {
            monthAttr = "0" + month;
        } else {
            monthAttr = month.toString();
        }
        return year + monthAttr;
    }

    /**
     * 给两个形如 202001   202003的字符串 解析并把两个相差的月份获取到
     *
     * @return
     */
    public static List<Date> parsDateAndGetMonthDifferences(String beginDateStr, String endDateStr) {
        String beginYear = beginDateStr.substring(0, 4);
        String beginMonth = beginDateStr.substring(4, 6);
        String endYear = endDateStr.substring(0, 4);
        String endMonth = endDateStr.substring(4, 6);
        Date beginDate = DateKit8.parse(beginYear + "-" + beginMonth + "-01", "yyyy-MM-dd");
        Date endDate = DateKit8.parse(endYear + "-" + endMonth + "-01", "yyyy-MM-dd");
        return getMonthDifferences(beginDate, endDate);
    }

    /**
     * 给一个形如 202001   202003的字符串 解析返回年月
     *
     * @param dateStr 时间字符串
     * @return
     */
    public static String[] getYearAndMonthByDateString(String dateStr) {
        ParamException.isTrue(dateStr.length() == 6 || dateStr.length() == 14, "传入日期格式有误，日期：" + dateStr);
        String[] yearAndMonth = new String[2];
        String year = dateStr.substring(0, 4);
        String month = dateStr.substring(4, 6);
        yearAndMonth[0] = year;
        yearAndMonth[1] = month;
        return yearAndMonth;
    }

    /**
     * 给一个形如 202001   202003的字符串 解析返回Date
     *
     * @param dateStr 时间字符串
     * @return Date
     */
    public static Date getDateByDateStr(String dateStr) {
        ParamException.isTrue(dateStr.length() == 6 || dateStr.length() == 14, "传入日期格式有误，日期：" + dateStr);
        String year = dateStr.substring(0, 4);
        String month = dateStr.substring(4, 6);
        return DateKit8.parse(year + "-" + month + "-01", "yyyy-MM-dd");
    }

    /**
     * 当前年
     *
     * @return 年
     */
    public static int getCurrentYear() {
        LocalDateTime localTime = LocalDateTime.now();
        return localTime.get(ChronoField.YEAR);
    }

    /**
     * 当前月
     *
     * @return 月
     */
    public static int getCurrentMonth() {
        LocalDateTime localTime = LocalDateTime.now();
        return localTime.get(ChronoField.MONTH_OF_YEAR);
    }

    /**
     * 当前月,小于10 前面加0
     */
    public static String getCurrentMonthStr() {
        LocalDateTime localTime = LocalDateTime.now();
        int month = localTime.get(ChronoField.MONTH_OF_YEAR);
        if (month < 10) {
            return "0" + month;
        } else {
            return month + "";
        }
    }

    /**
     * 当前日
     *
     * @return 日
     */
    public static String getCurrentDay() {
        String currentDayStr;
        LocalDateTime localTime = LocalDateTime.now();
        int currentDay = localTime.get(ChronoField.DAY_OF_MONTH);
        if (currentDay < 10) {
            currentDayStr = "0" + currentDay;
        } else {
            currentDayStr = currentDay + "";
        }
        return currentDayStr;
    }

    /**
     * 获取当前传入月的最后一天,如果传入月是系统当前时间,则返回系统当前月的当前天
     *
     * @param dateStr Date字符串
     * @return 天
     */
    public static String getMonthDayCount(String dateStr) {
        ParamException.isTrue(dateStr.length() == 6 || dateStr.length() == 14, "传入日期格式有误，日期：" + dateStr);
        String year = dateStr.substring(0, 4);
        String month = dateStr.substring(4, 6);

        if (getCurrentMonth() == Integer.parseInt(month)) {
            return getCurrentDay();
        } else {
            Calendar c = Calendar.getInstance();
            c.clear();
            c.set(Calendar.YEAR, Integer.parseInt(year));
            c.set(Calendar.MONTH, Integer.parseInt(month) - 1);
            return c.getActualMaximum(Calendar.DAY_OF_MONTH) + "";
        }
    }

    /**
     * 获取当前月的最后一天
     *
     * @return 最后一天
     */
    public static String getCurrentMonthDayCount() {
        Calendar c = Calendar.getInstance();
        c.clear();
        c.setTime(new Date());
        return c.getActualMaximum(Calendar.DAY_OF_MONTH) + "";
    }

    /**
     * 获取当前时间, 变成20210101 00:00:00 这种形式
     */
    public static String getYearMonthHaveMillisStr(Boolean haveMillis) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        String monthAttr;
        if (month < 10) {
            monthAttr = "0" + month;
        } else {
            monthAttr = month + "";
        }
        if (haveMillis) {
            LocalTime localTime = LocalTime.now().withNano(0);
            return year + monthAttr + day + " " + localTime.toString();
        } else {
            return year + monthAttr + day;
        }
    }

    /**
     * 找出最小的时间
     */
    public static Date compareMin(Date... dates) {
        List<Date> dateList = new ArrayList<>();
        for (Date date : dates) {
            if (!ObjectUtils.isEmpty(date)) {
                dateList.add(date);
            }
        }
        if (CollectionUtils.isEmpty(dateList)) {
            return null;
        }
        Date minDate = dateList.get(0);
        for (Date date : dateList) {
            if (minDate.after(date)) {
                minDate = date;
            }
        }
        return minDate;
    }

    /**
     * 给我一个Date 我给你 返回2020-01只有年月的形式
     */
    public static String getYearMonthByDate(Date date) {
        if (ObjectUtils.isEmpty(date)) {
            return "";
        }
        String dateStr = DateKit8.format2Date(date);
        return dateStr.substring(0, dateStr.lastIndexOf("-"));
    }

    /**
     * 根据格式返回时间字符串
     */
    public static String getDateStr(Date date, String dateFormat) {
        if (date != null && !StrKit.isEmpty(dateFormat)) {
            SimpleDateFormat format = new SimpleDateFormat(dateFormat);
            return format.format(date);
        } else {
            return "";
        }
    }

    /**
     * 当前时间距离当天结束还有多少毫秒
     */
    public static Integer getRemainMillisecondOneDay(Date currentDate) {
        LocalDateTime midnight = LocalDateTime.ofInstant(currentDate.toInstant(),
                        ZoneId.systemDefault()).plusDays(1).withHour(0).withMinute(0)
                .withSecond(0).withNano(0);
        LocalDateTime currentDateTime = LocalDateTime.ofInstant(currentDate.toInstant(),
                ZoneId.systemDefault());
        long seconds = ChronoUnit.SECONDS.between(currentDateTime, midnight);
        return (int) seconds * 1000;
    }

    /**
     * 判断两个时间范围是否有交集
     *
     * @param dynaStartTime  比较时间段开始时间
     * @param dynaEndTime    比较时间段结束时间
     * @param fixedStartTime 参考时间段开始时间
     * @param fixedEndTime   参考时间段结束时间
     * @return
     */
    public static Boolean checkTimesHasOverlap(Date dynaStartTime, Date dynaEndTime, Date fixedStartTime, Date fixedEndTime) {
        return !(dynaEndTime.getTime() < fixedStartTime.getTime() || dynaStartTime.getTime() > fixedEndTime.getTime());
    }

    /**
     * 判断一个时间是否在另外两个时间的范围内
     *
     * @param startTime   比较时间段开始时间
     * @param endTime     比较时间段结束时间
     * @param compareTime 参考时间段开始时间
     */
    public static Boolean compareWithinRange(Date startTime, Date endTime, String compareTime) {
        int startTimeInteger = Integer.parseInt(getYearMonthStr(startTime));
        int endTimeInteger = Integer.parseInt(getYearMonthStr(endTime));
        int compareTimeInteger = Integer.parseInt(compareTime);
        return compareTimeInteger >= startTimeInteger && compareTimeInteger <= endTimeInteger;
    }

    /**
     *
     * @return
     */
    public static Date locaDateToDate(LocalDate localDate){
        Date date = Date.from(localDate.atStartOfDay(ZoneOffset.ofHours(8)).toInstant());
        return date;
    }

    public static List<String> getMonthList(){
        return new ArrayList<String>() {{
            add("01");
            add("02");
            add("03");
            add("04");
            add("05");
            add("06");
            add("07");
            add("08");
            add("09");
            add("10");
            add("11");
            add("12");
        }};
    }

}